from chips import *
import select, sys
import time

# 模拟 8-BIT 计算机

# 各个模块
mods = {}   #模块字典
wire = {}   #连线字典
wire["bus"] = Wire(8)  #8位总线

# 时钟模块
timer = Timer()        # 时钟       HLT
wire["clk"] = Wire(1)(timer, 1)         # 正时钟输出    1
wire["n_clk"] = Wire(1)(timer, 2)       # 负时钟输出    2
wire["HLT"] = Wire(1)(timer, 0)         # 时钟停机      0

# 寄存器模块
rega = Register(8)      # 寄存器A   AI AO
wire["bus"](rega, rega.datamask)        # 输入接总线
wire["bus"](rega, slice(12, 20))        # 输出接总线
wire["clk"](rega, rega.clkmask)         # 时钟线
wire["AI"] = Wire(1)(rega, rega.eimask) # AI控制线
wire["AO"] = Wire(1)(rega, rega.eomask) # AO控制线
mods["寄存器A"] = rega

regb = Register(8)      # 寄存器B   BI
wire["bus"](regb, regb.datamask)        # 输入接总线
wire["clk"](regb, regb.clkmask)         # 时钟线
wire["BI"] = Wire(1)(regb, regb.eimask) # BI控制线
mods["寄存器B"] = regb

regi = Register(8)      # 寄存器I   II IO
wire["bus"](regi, regi.datamask)                # 输入接总线
wire["bus"](regi, slice(16, 20))                # 低4位输出接总线
wire["cmd"] = Wire(4)(regi.data, slice(0, 4))   # 高4位输出接译码器
wire["clk"](regi, regi.clkmask)                 # 时钟线
wire["II"] = Wire(1)(regi, regi.eimask)         # II控制线
wire["IO"] = Wire(1)(regi, regi.eomask)         # IO控制线
mods["寄存器I"] = regi

rego = Register(8)      # 寄存器O   OI
wire["bus"](rego, rego.datamask)        # 输入接总线
wire["clk"](rego, rego.clkmask)         # 时钟线
wire["OI"] = Wire(1)(rego, rego.eimask) # OI控制线
mods["寄存器O"] = rego

# 加减法计算模块
adder = Adder(8)        # 计算器    EO SU
wire["addi1"] = Wire(8)(adder, adder.data1mask) # 输入1接 rega 的数据
wire["addi1"](rega.data, slice(0, 8))
wire["addi2"] = Wire(8)(adder, adder.data2mask) # 输入2接 regb 的数据
wire["addi2"](regb.data, slice(0, 8))
wire["bus"](adder, slice(19, 27))               # 输出接总线
wire["EO"] = Wire(1)(adder, adder.eomask)       # EO控制线
wire["SU"] = Wire(1)(adder, adder.submask)      # SU控制线
mods["计算器"] = adder

# 程序计数器模块
icount = Counter(4)     # 程序计数器    CE J CO
wire["bus"](icount, icount.datamask)        # 输入接总线
wire["bus"](icount, slice(9, 13))           # 输出接总线
wire["clk"](icount, icount.clkmask)         # 时钟线
wire["CE"] = Wire(1)(icount, icount.enmask) # CE控制线
wire["J"] = Wire(1)(icount, icount.cimask)  # J控制线
wire["CO"] = Wire(1)(icount, icount.comask) # CO控制线
mods["程序计数器"] = icount

# 内存模块      
mem = Memory(4, 8)      # 内存16byte   MI RI RO
wire["bus"](mem, mem.addrmask)          # 地址输入接总线
wire["bus"](mem, mem.datamask)          # 数据输入接总线
wire["bus"](mem, slice(15, 23))         # 输出接总线
wire["MI"] = Wire(1)(mem, mem.aimask)   # MI控制线
wire["RI"] = Wire(1)(mem, mem.mimask)   # RI控制线
wire["RO"] = Wire(1)(mem, mem.momask)   # RO控制线
mods["内存"] = mem
# =======对内存进行编程=======
# 28和14的加法
# ===========================
mem.load_mem(0b0000, 0b00011110)        # 00 > LDA 14
mem.load_mem(0b0001, 0b00101111)        # 01 > ADD 15
mem.load_mem(0b0010, 0b11100000)        # 02 > OUT
mem.load_mem(0b0011, 0b11110000)        # 03 > HLT
mem.load_mem(0b1110, 0b00011100)        # 14 > (28)
mem.load_mem(0b1111, 0b00001110)        # 15 > (14)
# 不停+3
# ===========================
# mem.load_mem(0b0000, 0b01010011)        # 00 > LDI 3
# mem.load_mem(0b0001, 0b01001111)        # 01 > STA 15
# mem.load_mem(0b0010, 0b01010000)        # 02 > LDI 0
# mem.load_mem(0b0011, 0b00101111)        # 03 > ADD 15
# mem.load_mem(0b0100, 0b11100000)        # 04 > OUT
# mem.load_mem(0b0101, 0b01100011)        # 05 > JMP 3

# 微指令计数器模块
mcount = Counter(3)(0b00100000) # 微指令计数器  CE打开
wire["mcmd"] = Wire(3)(mcount.data, slice(0, 3))        # 微指令控制线
wire["n_clk"](mcount, 1)                                # 时钟线
mcreset = NOR(16)                                       # 微指令计数器重置器
wire["mcrst_set"] = Wire(16)(mcreset, mcreset.datamask) # 计数器重置器接线 NOP = 1
wire["mcrst_get"] = Wire(1)(mcreset, 16)                # 计数器重置器接线 NOP = 1
wire["mcrst_get"](mcount, mcount.rstmask)               # 计数器重置信号输入
mods["微指令计数器"] = mcount
mods["微重置器"] = mcreset

# 指令译码器模块
# 微指令集
# [HLT] [MI_] [RI_] [RO_] [IO_] [II_] [AI_] [AO_] [EO_] [SU_] [BI_] [OI_] [CE_] [CO_] [_J_]
#    0     1     2     3     4     5     6     7     8     9    10    11    12    13    14
mcmd_NP  = 0b0000000000000000
mcmd_HLT = 0b1000000000000000
mcmd_MI  = 0b0100000000000000
mcmd_RI  = 0b0010000000000000
mcmd_RO  = 0b0001000000000000
mcmd_IO  = 0b0000100000000000
mcmd_II  = 0b0000010000000000
mcmd_AI  = 0b0000001000000000
mcmd_AO  = 0b0000000100000000
mcmd_EO  = 0b0000000010000000
mcmd_SU  = 0b0000000001000000
mcmd_BI  = 0b0000000000100000
mcmd_OI  = 0b0000000000010000
mcmd_CE  = 0b0000000000001000
mcmd_CO  = 0b0000000000000100
mcmd_J   = 0b0000000000000010
# 指令集
gcmd_Nope  = [mcmd_NP]
gcmd_Fetch = [mcmd_CO|mcmd_MI, mcmd_RO|mcmd_II|mcmd_CE]
# 可用指令
cmd_NOP = gcmd_Fetch + gcmd_Nope * 6
cmd_LDA = gcmd_Fetch + [mcmd_IO|mcmd_MI, mcmd_RO|mcmd_AI] + gcmd_Nope * 4
cmd_ADD = gcmd_Fetch + [mcmd_IO|mcmd_MI, mcmd_RO|mcmd_BI, mcmd_EO|mcmd_AI] + gcmd_Nope * 3
cmd_SUB = gcmd_Fetch + [mcmd_IO|mcmd_MI, mcmd_RO|mcmd_BI, mcmd_EO|mcmd_AI|mcmd_SU] + gcmd_Nope * 3
cmd_STA = gcmd_Fetch + [mcmd_IO|mcmd_MI, mcmd_AO|mcmd_RI] + gcmd_Nope * 4
cmd_LDI = gcmd_Fetch + [mcmd_IO|mcmd_AI] + gcmd_Nope * 5
cmd_JMP = gcmd_Fetch + [mcmd_IO|mcmd_J ] + gcmd_Nope * 5
# ......
cmd_OUT = gcmd_Fetch + [mcmd_AO|mcmd_OI] + gcmd_Nope * 5
cmd_HLT = gcmd_Fetch + [mcmd_HLT] + gcmd_Nope * 5
# 编码到rom中
rom = cmd_NOP + cmd_LDA + cmd_ADD + cmd_SUB + cmd_STA + cmd_LDI + cmd_JMP + cmd_NOP + cmd_NOP + cmd_NOP + cmd_NOP + cmd_NOP + cmd_NOP + cmd_NOP + cmd_OUT + cmd_HLT

command = PROM(7, 16, rom)              # 指令译码器
wire["cmd"](command, slice(0, 4))       # 高4位接指令输入
wire["mcmd"](command, slice(4, 7))      # 低3位接微计数器输入

wire["HLT"](command, 7)                 # HLT输出控制
wire["MI"](command,  8)                 # MI 输出控制
wire["RI"](command,  9)                 # RI 输出控制
wire["RO"](command, 10)                 # RO 输出控制
wire["IO"](command, 11)                 # IO 输出控制
wire["II"](command, 12)                 # II 输出控制
wire["AI"](command, 13)                 # AI 输出控制
wire["AO"](command, 14)                 # AO 输出控制
wire["EO"](command, 15)                 # EO 输出控制
wire["SU"](command, 16)                 # SU 输出控制
wire["BI"](command, 17)                 # BI 输出控制
wire["OI"](command, 18)                 # OI 输出控制
wire["CE"](command, 19)                 # CE 输出控制
wire["CO"](command, 20)                 # CO 输出控制
wire["J"](command,  21)                 # J  输出控制
wire["mcrst_set"](command, slice(7, 23))# 微计数器重置控制
mods["指令译码器"] = command

def auto_detail(mods):
    max_name_len = len(max(mods, key=len))
    print("--------------------------------------------------------------------------")
    for name in mods :
        if hasattr(mods[name], "data") :
            print( ("{:\u3000>%ds}"%max_name_len).format(name), "\t: <数据>:[%s]"%mods[name].data )
        print( ("{:\u3000>%ds}"%max_name_len).format(name), "\t: <输入>:[%s] <输出>:[%s]"%(mods[name].pinIN, mods[name].pinOUT) )
    print("--------------------------------------------------------------------------")

print("\033[2J\033[?25l")

try :
    while not timer[0]:
        print("\033[0;0H\033[K\033[33m[运行] \033[0m运算结果:\033[1;34m%04d  \033[0m时钟:\033[1;32m%s\033[0m"%(rego.data(), "UP" if timer[1] else "DOWN"))
        timer.update(step=True)
        if select.select([sys.stdin, ], [], [], 0.0)[0]:
            user_input = sys.stdin.read()
            if user_input == "\x01" : break
        for i in wire : wire[i].update()
        for i in mods : mods[i].update()
        for i in wire : wire[i].update()
        for i in mods : mods[i].update()
        time.sleep(0.05)
        auto_detail(mods)
        print("\t总线\t: <数据>:[{:0>8b}]".format(wire["bus"].data))
except : pass
finally : 
    print("\033[0;0H\033[K\033[31m[停机]\033[0m 运算结果:\033[1;34m%04d\033[?25h"%rego.data())
    print("\033[22;0H")